/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.recycler.coverflow.recyclerview;

import com.recycler.coverflow.adapter.Adapter;
import com.recycler.coverflow.utils.PixelUtil;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ListContainer;

import ohos.app.Context;

/**
 * 自定义ListContainer.
 */
public class MyListContainer extends ListContainer {
    // 旋转木马子view
    private int mIndex = 2;
    // 原始宽
    private int originWidth;

    private OnCurrentItemListener onCurrentItemListener;

    public MyListContainer(Context context) {
        this(context, null);
    }

    public MyListContainer(Context context, AttrSet attrSet) {
        this(context, attrSet, "");
    }

    public MyListContainer(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        originWidth = PixelUtil.screenWidth() / 5;

        setLayoutRefreshedListener(new LayoutRefreshedListener() {
            @Override
            public void onRefreshed(Component component) {
                mIndex = getScrollValue(AXIS_X) / originWidth + 2;
                if (mIndex == 2) {
                    ((Adapter) getItemProvider()).addNewData(MyListContainer.this, originWidth);
                }
                refreshLayout(getScrollValue(AXIS_X));
                if (onCurrentItemListener != null) {
                    onCurrentItemListener.onCurrentItem(mIndex);
                }
            }
        });
    }

    /**
     * setOnCurrentItemListener.
     *
     * @param onCurrentItemListener onCurrentItemListener
     */
    public void setOnCurrentItemListener(OnCurrentItemListener onCurrentItemListener) {
        this.onCurrentItemListener = onCurrentItemListener;
    }

    private void refreshLayout(float distanceX) {
        refreshTotal(distanceX);
        LayoutConfig config = new LayoutConfig();
        config.height = (int) (getItem(mIndex).getHeight() * 1.5f + 100);
        setLayoutConfig(config);
        invalidate();
    }

    /**
     * 获取当前index.
     *
     * @return 获取当前index
     */
    public int getIndex() {
        return mIndex;
    }

    private void refreshTotal(float distanceX) {
        Component beforeC;
        Component centC;
        Component afterC;
        if (mIndex - 3 >= 0) {
            refreshItem(distanceX, getItem(mIndex - 3), mIndex - 3);
        }
        float scale1 = refreshItem(distanceX, getItem(mIndex - 2), mIndex - 2);
        float scale2 = refreshItem(distanceX, beforeC = getItem(mIndex - 1), mIndex - 1);
        float scale3 = refreshItem(distanceX, centC = getItem(mIndex), mIndex);
        float scale4 = refreshItem(distanceX, afterC = getItem(mIndex + 1), mIndex + 1);
        float scale5 = refreshItem(distanceX, getItem(mIndex + 2), mIndex + 2);
        if (mIndex + 3 <= getItemProvider().getCount()) {
            refreshItem(distanceX, getItem(mIndex + 3), mIndex + 3);
        }

        float scaleMax1 = Math.max(scale2, Math.max(scale3, scale4));
        if (scaleMax1 == scale2) {
            moveChildToFront(afterC);
            moveChildToFront(centC);
            moveChildToFront(beforeC);
        } else if (scaleMax1 == scale3) {
            moveChildToFront(afterC);
            moveChildToFront(beforeC);
            moveChildToFront(centC);
        } else if (scaleMax1 == scale4) {
            moveChildToFront(beforeC);
            moveChildToFront(centC);
            moveChildToFront(afterC);
        }

    }

    private float refreshItem(float distanceX, Component child, int index) {
        float scale = calcScale(distanceX, child.getLocationOnScreen(), index);
        child.setScale(scale, scale);
        return scale;
    }

    private Component getItem(int index) {
        Component itemComponent = ((Adapter) getItemProvider()).getItemComponent(index);
        itemComponent.setTranslationY(100);
        return itemComponent;
    }

    private float calcScale(float distanceX, int[] location, int posi) {
        float scale = 0;
        if (posi == mIndex) {
            scale = (float) (1.5 - ((Math.abs(distanceX - (mIndex - 2) * originWidth) / originWidth) * 0.25));
        } else if (posi == mIndex - 1) {
            int move = (int) (distanceX - (mIndex - 2) * originWidth);
            if (move < 0) {
                scale = (float) (1.25 + ((Math.abs(distanceX - (mIndex - 2) * originWidth) / originWidth) * 0.25));
            } else {
                scale = (float) (1.25 - ((Math.abs(distanceX - (mIndex - 2) * originWidth) / originWidth) * 0.25));
            }
        } else if (posi == mIndex - 2) {
            int move = (int) (distanceX - (mIndex - 2) * originWidth);
            if (move < 0) {
                scale = (float) (1 + ((Math.abs(distanceX - (mIndex - 2) * originWidth) / originWidth) * 0.25));
            } else {
                scale = (float) (1 - ((Math.abs(distanceX - (mIndex - 2) * originWidth) / originWidth) * 0.25));
            }
        } else if (posi == mIndex + 1) {
            int move = (int) (distanceX - (mIndex - 2) * originWidth);
            if (move > 0) {
                scale = (float) (1.25 + ((Math.abs(distanceX - (mIndex - 2) * originWidth) / originWidth) * 0.25));
            } else {
                scale = (float) (1.25 - ((Math.abs(distanceX - (mIndex - 2) * originWidth) / originWidth) * 0.25));
            }
        } else if (posi == mIndex + 2) {
            int move = (int) (distanceX - (mIndex - 2) * originWidth);
            if (move > 0) {
                scale = (float) (1 + ((Math.abs(distanceX - (mIndex - 2) * originWidth) / originWidth) * 0.25));
            } else {
                scale = (float) (1 - ((Math.abs(distanceX - (mIndex - 2) * originWidth) / originWidth) * 0.25));
            }
        } else if (posi == mIndex + 3) {
            scale = 1;
        } else if (posi == mIndex - 3) {
            scale = 1;
        }
        return scale;
    }

    /**
     * OnCurrentItemListener.
     */
    public interface OnCurrentItemListener {
        /**
         * onCurrentItem.
         *
         * @param posstion posstion
         */
        void onCurrentItem(int posstion);
    }
}
